package tests.pl.shenlon.poker.cards.evaluation;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;

import pl.shenlon.poker.cards.CardUtils;
import pl.shenlon.poker.cards.Hand;
import pl.shenlon.poker.cards.deck.Deck;
import pl.shenlon.poker.cards.deck.PokerDeck;
import pl.shenlon.poker.cards.evaluation.PotOddsEvaluator;

public class PotOddsCalculatorTest {

	private PotOddsEvaluator calculator;

	private Deck deck;

	@Before
	public void setUp() {
		calculator = new PotOddsEvaluator();
		deck = new PokerDeck();
	}

	@Test
	public void testEvaluatingDetailedOddsForEveryPreFlopCombination() {
		for (int i = 0; i < deck.length; i++) {
			for (int j = 0; j < deck.length; j++) {
				if (j == i) {
					continue;
				}
				Hand hand = new Hand(deck.getCardAtPosition(i),
						deck.getCardAtPosition(j));
				Assert.assertNotNull(calculator
						.getDetailedPreFlopHandOdds(hand));
			}
		}
	}

	@Test
	public void testEvaluatingDetailedOddsForFlopCombination() {
		for (int i = 0; i < 10; i++) {
			deck.shuffle();
			Hand hand = new Hand(deck.next(), deck.next(), deck.next(),
					deck.next(), deck.next());
			Assert.assertNotNull(calculator.getDetailedFlopHandOdds(hand));
		}
	}

	@Test
	public void testEvaluatingDetailedOddsForTurnCombination() {
		for (int i = 0; i < 10; i++) {
			deck.shuffle();
			Hand hand = new Hand(deck.next(), deck.next(), deck.next(),
					deck.next(), deck.next(), deck.next());
			Assert.assertNotNull(calculator.getDetailedTurnHandOdds(hand));
		}
	}

	@Test
	public void testEvaluatingOverallOdds() {
		deck.shuffle();
		Hand hand = new Hand(deck.next(), deck.next());
		Hand table = new Hand(deck.next(), deck.next(), deck.next(),
				deck.next(), deck.next());
		Assert.assertEquals(calculator.getOverallPreFlopHandOdds(hand),
				calculator.getOverallHandOdds(hand, table), 1e-3);
		for (int i = 0; i < 3; i++) {
			table.getCard(i).setFaceUp(true);
		}
		Assert.assertEquals(calculator.getOverallFlopHandOdds(CardUtils
				.joinHands(hand, table)),
				calculator.getOverallHandOdds(hand, table), 1e-3);
		table.getCard(3).setFaceUp(true);
		Assert.assertEquals(calculator.getOverallTurnHandOdds(CardUtils
				.joinHands(hand, table)), calculator.getOverallHandOdds(hand,
				table), 1e-3);
	}

	@Test
	public void testEvaluatingOverallOddsForEveryPreFlopCombination() {
		for (int i = 0; i < deck.length; i++) {
			for (int j = 0; j < deck.length; j++) {
				if (j == i) {
					continue;
				}
				Hand hand = new Hand(deck.getCardAtPosition(i),
						deck.getCardAtPosition(j));
				Assert.assertTrue(calculator.getOverallPreFlopHandOdds(hand) > 0.0);
			}
		}
	}

	@Test
	public void testEvaluatingOverallOddsForFlopCombination() {
		for (int i = 0; i < 10; i++) {
			deck.shuffle();
			Hand hand = new Hand(deck.next(), deck.next(), deck.next(),
					deck.next(), deck.next());
			Assert.assertTrue(calculator.getOverallFlopHandOdds(hand) > 0);
		}
	}

	@Test
	public void testEvaluatingOverallOddsForTurnCombination() {
		for (int i = 0; i < 10; i++) {
			deck.shuffle();
			Hand hand = new Hand(deck.next(), deck.next(), deck.next(),
					deck.next(), deck.next(), deck.next());
			Assert.assertTrue(calculator.getOverallTurnHandOdds(hand) >= 0);
		}
	}

	@Test
	public void testGetOverallFlopHandOdds() {
		Hand hand = new Hand("2♠-4♠-10♠-J♠-K♠");
		Assert.assertEquals(
				2.0 / PotOddsEvaluator.POSSIBLE_CARD_COMBINATIONS_FLOP_COUNT,
				calculator.getOverallFlopHandOdds(hand), 1e-4);
	}

	@Test
	public void testGetPrefixPosition() {
		for (int i = PotOddsEvaluator.PREFIXES.length - 1; i >= 0; i--) {
			Assert.assertEquals(i,
					calculator.getPrefixPosition(PotOddsEvaluator.PREFIXES[i]));
		}
		Assert.assertEquals(-1,
				calculator.getPrefixPosition("NON_EXISTANT_PREFIX"));
	}
}